/*********************************************************************************
* Copyright (c) zhujinyang.
* All rights reserved.
*
* \file
*
* main
*
* 
*********************************************************************************/
#include "os_ext_api.h"
#include "stm32h7xx_ll_rcc.h"
#include "stm32h7xx_ll_bus.h"
#include "stm32h7xx_ll_utils.h"
#include "stm32h7xx_ll_pwr.h"
#include "stm32h7xx_ll_cortex.h"
#include "hal_irq_drv.h"
#include "hal_uart_drv.h"
#include "hal_gpio_drv.h"
//#include "hal_can_drv.h"
//#include "hal_adc_drv.h"
//#include "hal_iic_drv.h"
//#include "hal_flash_drv.h"
#include "g_cfg.h"

void mal_main_init(void);

void SystemClock_Config(void)
{
  LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);

  LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
  while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_4)
  {
  }
  LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
  LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
  while (LL_PWR_IsActiveFlag_VOS() == 0)
  {
  }
  LL_RCC_HSE_Enable();

   /* Wait till HSE is ready */
  while(LL_RCC_HSE_IsReady() != 1)
  {

  }
  LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSE);
  LL_RCC_PLL1P_Enable();
  LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_4_8);
  LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
  LL_RCC_PLL1_SetM(5);
  LL_RCC_PLL1_SetN(192);
  LL_RCC_PLL1_SetP(2);
  LL_RCC_PLL1_SetQ(2);
  LL_RCC_PLL1_SetR(2);
  LL_RCC_PLL1_Enable();

   /* Wait till PLL is ready */
  while(LL_RCC_PLL1_IsReady() != 1)
  {
  }

   /* Intermediate AHB prescaler 2 when target frequency clock is higher than 80 MHz */
   LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);

  LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);

   /* Wait till System clock is ready */
  while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1)
  {

  }
  LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
  LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
  LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
  LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
  LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
  LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);

  LL_RCC_SetUSARTClockSource(LL_RCC_USART16_CLKSOURCE_PCLK2);
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOC);
  LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOD);
  
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
  LL_AHB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
  
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_D2SRAM1);
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_D2SRAM2);
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_D2SRAM3);
  
  LL_Init1msTick(480000000);

  LL_SetSystemCoreClock(480000000);
  
  SysTick_Config((480000000 / 1000000) * OS_TICK_US);
}





void mpu_config(void)
{
    INT8U i;
    struct {
        INT32U base_addr;
        INT32U attr;
    } cfg[] = {
        {FLASH_BASE_ADDR,   LL_MPU_REGION_SIZE_2MB | LL_MPU_REGION_PRIV_RO_URO | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_ENABLE | LL_MPU_ACCESS_NOT_SHAREABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_BUFFERABLE},
        {AXISRAM_BASE_ADDR, LL_MPU_REGION_SIZE_512KB | LL_MPU_REGION_FULL_ACCESS | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_DISABLE | LL_MPU_ACCESS_NOT_SHAREABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_BUFFERABLE},
        {D2SRAM_BASE_ADDR,  LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_DISABLE | LL_MPU_ACCESS_NOT_SHAREABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_BUFFERABLE},
        {D3SRAM_BASE_ADDR,  LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_DISABLE | LL_MPU_ACCESS_NOT_SHAREABLE | LL_MPU_ACCESS_CACHEABLE | LL_MPU_ACCESS_BUFFERABLE},
        {NOCACHE_BASE_ADDR, LL_MPU_REGION_SIZE_32KB | LL_MPU_REGION_FULL_ACCESS | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_DISABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_ACCESS_NOT_CACHEABLE | LL_MPU_ACCESS_NOT_BUFFERABLE},
        {0x40000000,        LL_MPU_REGION_SIZE_512MB | LL_MPU_REGION_FULL_ACCESS | LL_MPU_TEX_LEVEL1 | LL_MPU_INSTRUCTION_ACCESS_DISABLE | LL_MPU_ACCESS_SHAREABLE | LL_MPU_ACCESS_NOT_CACHEABLE | LL_MPU_ACCESS_NOT_BUFFERABLE},
    };
    
    LL_MPU_Disable(); 

    for (i = 0; i < sizeof(cfg)/sizeof(cfg[0]); i++) {
        LL_MPU_ConfigRegion(i, 0, cfg[i].base_addr, cfg[i].attr);
    }

    LL_MPU_Enable(LL_MPU_CTRL_HFNMI_PRIVDEF); 
    
}


int main(void) 
{

    SystemClock_Config();                                                       
    mpu_config();
    SCB_EnableICache();
    SCB_EnableDCache();
    
    /* os core must initialize first */
    os_core_init();
    
    hal_irq_initdrv();
    hal_gpio_initdrv();
    hal_uart_initdrv();
    //hal_can_initdrv();
    //hal_adc_initdrv();
    //hal_iic_initdrv();
    //hal_flash_initdrv();


    
    mal_main_init();

    os_sched_start();
}




